# include <reg52.h>
# include <math.h>
# define ON 10
# define ADD 11
# define SUB 12
# define MUL 13
# define DIV 14
# define EQU 15
# define BLANK 10
# define ERROR 11
# define MINUS 12
sbit SPEAKER = P3^7;
long Result,VarTmp;
unsigned char code LED[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0x86,0xbf};
unsigned char code KeyTable[] ={ON,0,EQU,ADD,1,2,3,SUB,4,5,6,MUL,7,8,9,DIV};
unsigned char DisplayNo,Operate,MS,DisplayBuffer[8];


bit Over,NoError = 1,FirstInput=1;

unsigned int BeepTime;
void delayms(unsigned int x);
void ModifyDisplayBuffer(long num);
void Calculate();
void ClrDisplayBuffer();

void Delay(unsigned char i)
{
        MS=i;
        while(MS);
}

unsigned char Key()
{
    unsigned char Row,Col,k;
    P1=0x0f;
    k = P1&0x0f;


    if(k == 0x0f)  return 0xff;
    delayms(20);
    k = P1&0x0f;
    if(k == 0x0f)  return 0xff;
    BeepTime = 300;
    for(Row = 0;Row <4;Row++)
    {
        P1=0x7f >> Row;
        k=P1&0x0f;
        if(k!=0x0f){
            Col=0;
            while(k&(1 << Col))     Col++;
            break;
        }
    }
    while((P1&0x0f) != 0x0f);
    k = Row + Col * 4;
    return KeyTable[k];

}

void KeyProcess(unsigned char k)
{
    if(k == ON)
    {
        Result = 0, VarTmp=0,Operate=0,Over=0,NoError=1,FirstInput=1;
        ClrDisplayBuffer();
    }
    if(!NoError)    return;
    if(k<10)
    {
        if(Over)    Over=0,VarTmp=0,Result=0,Operate=0,FirstInput = 1;
        VarTmp = VarTmp * 10 + k;
        if(VarTmp > 9999999)    VarTmp = VarTmp/10;
        if(Operate)    FirstInput = 0;
        ModifyDisplayBuffer(VarTmp);
    }
    if(k > 10 && k < 15)
    {
        if(Over)
        {
            Over = 0,VarTmp=0,FirstInput=1,Operate=k;
            return;
        }
        if(Operate && FirstInput == 0)
        {
            Calculate();
            VarTmp = 0,FirstInput = 1;
        }
        if(Operate == 0)
        {
            Result = VarTmp;
            VarTmp = 0;
        }
        Operate = k;
    }
    if(k == EQU)
    {
        if(Operate && FirstInput ==0)
        {
            Calculate();
            Over = 1;
        }
    }
}

void ClrDisplayBuffer()
{
    unsigned char i;
    for(i=0;i<7;i++)
        DisplayBuffer[i] = BLANK;
    DisplayBuffer[7] = 0;
}

void ModifyDisplayBuffer(long num)
{
    unsigned char i;
        if(num > 9999999 || num < -9999999)
        {
            ClrDisplayBuffer();
            DisplayBuffer[0] = ERROR;
            NoError = 0;
            return;
        }
        ClrDisplayBuffer();
        if(num < 0 )
        {
            num = labs(num);
            DisplayBuffer[0]=MINUS;
        }
        i=7;
        do{
            DisplayBuffer[i] = num % 10;
            num/=10;
            i--;
        }while(num != 0);
}

void Calculate()
{
    switch (Operate)
    {
        case ADD:
            Result = Result + VarTmp;
            ModifyDisplayBuffer(Result);
            break;
        
        case SUB:
            Result = Result - VarTmp;
            ModifyDisplayBuffer(Result);
            break;
        
        case MUL:
            Result = Result * VarTmp;
            ModifyDisplayBuffer(Result);
            break;
        
        case DIV:
            if(VarTmp != 0)
            {
                Result = Result / VarTmp;
                ModifyDisplayBuffer(Result);
            }
            else{
                ClrDisplayBuffer();
                DisplayBuffer[0]=ERROR;
                NoError = 0;
            }
            break;
    }
}

void main()
{
    unsigned char k;
        TMOD=1;
        TR0=1;
        ET0=1;
        EA=1;
        ClrDisplayBuffer();
        while(1)
        {
                k=Key();
                if(k!=0xff)
                    KeyProcess(k);
        }
}

void Display() interrupt 1
{
    TL0 = 64536 %256;
    TH0 = 64536 /256;
    if(MS)  MS--;
    if(BeepTime)
    {
        BeepTime--;
        SPEAKER = ~SPEAKER;
    }
    P2 = 0;
    P0 = LED[DisplayBuffer[DisplayNo]];
    P2 = 1 << DisplayNo;
    if(++DisplayNo == 8)
        DisplayNo = 0;
}

void delayms(unsigned int x)
{
	unsigned char i;
	while(x--)
		for(i=0;i<123;i++);	


}